package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	
	public class DisplayObjectLoader
	{
		private static var m_cachedBitmapDataByUrl:Object = new Object();
		private static var m_urlByLoader:Dictionary = new Dictionary(true);
		private static var m_containersWaitingForData:Object = new Object();
		private static var m_callbacks:Dictionary = new Dictionary(true);
		
		public function DisplayObjectLoader()
		{
		}
		
		
		public static function load(url:String, defaultWidth:int=0, defaultHeight:int=0, onLoadComplete:Function=null, container:DisplayObjectContainer = null):DisplayObjectContainer{
			var spr:DisplayObjectContainer;
			if(container){
				spr = container;
			} else {
				spr = new Sprite();
				(spr as Sprite).graphics.drawRect(0,0,defaultWidth, defaultHeight);
			}
			
			var bmd:BitmapData = m_cachedBitmapDataByUrl[url];
			
			if(bmd != null){
				spr.addChild(new Bitmap(bmd));
				if(onLoadComplete != null){
					onLoadComplete(spr);
				}
			} else {
				if(m_containersWaitingForData[url] == null){
					m_containersWaitingForData[url] = new Vector.<Sprite>;
					var ldr:Loader = new Loader();
					ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
					ldr.load(new URLRequest(url));
						
					m_urlByLoader[ldr] = url;
				}
				
				
				m_containersWaitingForData[url].push(spr);
				m_callbacks[spr] = onLoadComplete;
			}
			
			return spr;
		}
		
		private static function loadComplete(e:Event):void{
			var displayObject:DisplayObject = (e.currentTarget as LoaderInfo).content as DisplayObject;
			var ldr:Loader = (e.currentTarget as LoaderInfo).loader;
			var i:int, il:int;
			var container:Sprite;
			var url:String = m_urlByLoader[ldr];
			var containersWaitingForData:Vector.<Sprite> = m_containersWaitingForData[url] as Vector.<Sprite>;
			var callback:Function;
			
			if(displayObject is Bitmap){
				m_cachedBitmapDataByUrl[url] = (displayObject as Bitmap).bitmapData;
			} else if(displayObject is MovieClip){
				var child:* = (displayObject as MovieClip).getChildAt(0);
				if(child is Bitmap){
					m_cachedBitmapDataByUrl[url] = (child as Bitmap).bitmapData;
				}
			}					
			
			for(i = 0, il = containersWaitingForData.length; i < il; i++){
				container = containersWaitingForData[i];
				container.addChild(new Bitmap(m_cachedBitmapDataByUrl[url]));
				callback = m_callbacks[container];
				
				if(callback != null) {
					callback(container);
				}
			}
			
			m_callbacks[container] = null;
			m_containersWaitingForData[url] = null;
			delete m_callbacks[container];
			delete m_containersWaitingForData[url];			
		}
		
	}
}